home *** CD-ROM | disk | FTP | other *** search
/ More MacCube 2: Games / More MacCube Vol 2 Games.bin / Games / Xconq 7.0.1 / doc / hacking.texi < prev    next >
Encoding:
Text File  |  1995-08-22  |  48.7 KB  |  1,287 lines  |  [TEXT/MPS ]

  1. @node Hacking Xconq, , Reference Manual, Top
  2.  
  3. @chapter Hacking Xconq
  4.  
  5. Although @i{Xconq} and its GDL have considerable power and flexibility
  6. already built in,
  7. you may decide that you want to modify the @i{Xconq} program itself.
  8. You should know what you are doing;
  9. @i{Xconq} is designed to be modifiable, but it is not simple code.
  10. In the past, people have found it easy to make changes,
  11. but much harder to make them correctly!
  12.  
  13. @i{Xconq} is designed to be portable to different types of user interfaces.
  14. It is based on a kernel-interface architecture, where the semantics of
  15. the game, as documented in the preceding chapters, is part of the kernel,
  16. while the main program and player interaction are specific to each system.
  17.  
  18. @i{Xconq} is also designed to allow the addition of new AIs.  The default
  19. @code{"mplayer"} AI, while it is flexible and will attempt to play any side
  20. in any game, does not have the depth that is often important to success
  21. in a game.  Its position is that of a generic AI program that can learn to
  22. play any game, given only the rules; while such a program might figure out
  23. how to win at tic-tac-toe or checkers, it is not going to be particularly
  24. good at the subtleties of go or chess.
  25.  
  26. The @i{Xconq} GDL is also extensible.  This is useful when the basic GDL
  27. does not provide some feature that is essential to a game.
  28.  
  29. @menu
  30. * Kernel::                      
  31. * Interface::
  32. * Networking::                  
  33. * Miscellany::                  
  34. @end menu
  35.  
  36. @node Kernel, Interface, Hacking Xconq, Hacking Xconq
  37.  
  38. @section Kernel
  39.  
  40. The kernel is the part of @i{Xconq} shared by all interfaces.
  41. It does no I/O except to files or for debugging.
  42.  
  43. Specifically, the kernel supplies the following functionality:
  44. @itemize
  45. @item
  46. Data structure initialization. (@code{init_data_structures})
  47.  
  48. @item
  49. Game module loading and interpretation. (@code{load_game_module})
  50.  
  51. @item
  52. Initial player/side setup. (@code{make_trial_assignments})
  53.  
  54. @item
  55. Synthesis methods. (@code{run_synthesis_methods})
  56.  
  57. @item
  58. Final player/side setup. (@code{make_assignments})
  59.  
  60. @item
  61. Game execution. (@code{run_game})
  62.  
  63. @item
  64. Implementations of unit actions. (@code{prep_*_action})
  65.  
  66. @item
  67. AI players.
  68.  
  69. @item
  70. Help Info (@code{get_help_text})
  71.  
  72. @item
  73. Game saving and scorekeeping.
  74. @end itemize
  75.  
  76. @menu
  77. * Configuration Options::       
  78. * Porting the Kernel::          
  79. * Writing New Synthesis Methods::  
  80. * Writing New Namers::          
  81. * Writing New AIs::             
  82. * Extending GDL::               
  83. @end menu
  84.  
  85. @node Configuration Options, Porting the Kernel, Kernel, Kernel
  86.  
  87. @subsection Configuration Options
  88.  
  89. There are a small number of options available to alter aspects of
  90. the kernel.  These are defined in @code{kernel/config.h}.
  91.  
  92. [eventually describe all of them?]
  93.  
  94. @node Porting the Kernel, Writing New Synthesis Methods, Configuration Options, Kernel
  95.  
  96. @subsection Porting the Kernel
  97.  
  98. The kernel should be restricted to ANSI C, and should avoid or optionalize
  99. features not in ``traditional'' C, such like prototypes.
  100. Although the kernel uses stdio,
  101. it does not assume the presence of a console (stdin, stdout, stderr).
  102. For instance, a graphical interface can arrange to disable stdin entirely
  103. and direct stdout/stderr into a file (see the Mac interface sources
  104. for an example).
  105.  
  106. You should be careful about memory consumption.  In general, the kernel
  107. takes the attitude that if it was worth allocating, it's worth hanging
  108. onto; and so the program does not free much storage.  Also, nearly all
  109. of the allocation happens during startup.  Since a game may run for a
  110. very long time (thousands of turns perhaps), it is important not to
  111. run the risk of exhausting memory at a climactic moment in the game!
  112.  
  113. Also, the kernel should not exit on its own.  The only permissible
  114. times are when the internal state is so damaged that interface
  115. error-handling routines (see below) cannot be called safely.
  116. Such situations are rare.  If you add something to the kernel
  117. and need to handle error situations, then you should call one
  118. of the interface's error-handling routines.
  119. There are distinct routines for problems during initializations
  120. vs problems while running, and both error and warning routines.
  121. Warning routines may return, so kernel code should be prepared
  122. to continue on, while error routines will never return.
  123.  
  124. @node Writing New Synthesis Methods, Writing New Namers, Porting the Kernel, Kernel
  125.  
  126. @subsection Writing New Synthesis Methods
  127.  
  128. You can add new synthesis methods to @i{Xconq}.
  129. This may be necessary if an external program
  130. does not exist, is unsuitable, or the external program
  131. interface is not available.
  132. Synthesis methods should start out by testing whether or not to run,
  133. and should never assume that any other method has been run before or
  134. after, nor that any particular game module has been loaded.
  135. However, ``tricks'' are usually OK, such as setting a particular global
  136. variable in a particular module only, then having the synthesis method
  137. test whether that global is set.
  138. See the file @code{init.c} for further details.
  139.  
  140. Synthesis methods that take longer than a second or two to execute
  141. should generate percent-done info for the interface to use,
  142. via the function @code{announce_progress}.
  143. Be aware that most methods will be O(n) or O(n*n) on the
  144. size of the world or the number of units,
  145. so they can take much longer to set up
  146. a large game than a small one.
  147. Players will often go overboard and start up giant games,
  148. so this happens frequently.
  149. Also, @i{Xconq} may be running on a much smaller and slower
  150. machine than what you're using now.
  151.  
  152. @node Writing New Namers, Writing New AIs, Writing New Synthesis Methods, Kernel
  153.  
  154. @subsection Writing New Namers
  155.  
  156. [describe hook and interface]
  157.  
  158. @node Writing New AIs, Extending GDL, Writing New Namers, Kernel
  159.  
  160. @subsection Writing New AIs
  161.  
  162. You can add new types of AIs to @i{Xconq}.
  163. You would do this to add different strategies as well as
  164. to add AIs that are programmed specifically for a single game or
  165. class of games.  (This is useful because the generic AI does not
  166. always understand the appropriate strategy for each game.)
  167.  
  168. You have to design the object that is the AI's ``mental state''.
  169. If your AI need only react to the immediate situation, then this
  170. object can be very simple, but in general you will need to design
  171. a fairly elaborate structure with a number of substructures.
  172. Since there may be several AIs in a single game, you should be
  173. careful about using globals, and since @i{Xconq} games may often
  174. run for a long time, you should be careful not to consume memory
  175. recklessly.
  176.  
  177. @itemize
  178. @item
  179. Name.
  180. This is a string, such as @code{"mplayer"}.
  181. It may be displayed to players, so it should not be too cryptic.
  182.  
  183. @item
  184. Validity function.
  185. This runs after modules are loaded, and during player/side
  186. setup, and decides whether it can be in the given game on the given side.
  187. [have a chain of fallback AIs, or blow off the game?]
  188.  
  189. @item
  190. Game init function.  This runs before displays are set up, just in case
  191. a display needs to examine the AI's data (for instance to display whether
  192. the AI is friendly or unfriendly).
  193.  
  194. The game init function should also look for and interpret the contents
  195. of the side's @code{aidata}, if appropriate.  The generic game reading code
  196. fills the slot, but does not interpret the data further.
  197.  
  198. @item
  199. Turn init function.  This runs after all the units get their acp and mp
  200. for the turn, but before anybody actually gets to move.
  201.  
  202. @item
  203. Unit order function.  This gets run to decide what the unit should do.
  204. Usually it should be allowed to follow its plan.
  205. [do separate fns for before and after plan execution?]
  206.  
  207. @item
  208. Event reaction functions. [how many?]
  209.  
  210. @item
  211. State save function.  This formats state that should be saved into
  212. a Lisp object.  The game saving code then writes this state into
  213. the file so that it can be read in again.  You may not do any
  214. allocation while saving a game however, so if you need space (and
  215. note that even a single cons allocates space), you must have the AI
  216. init routine or some such do the allocation early on, then reuse
  217. the space.
  218.  
  219. @end itemize
  220.  
  221. Note that these functions have very few constraints, so you can write them
  222. to work together in various ways.  For instance, an AI can decide whether
  223. to resign once/turn, once/action, or once for each 4 units it moves, every
  224. other turn.
  225.  
  226. [describe default AI as illustrative example]
  227.  
  228. @node Extending GDL, , Writing New AIs, Kernel
  229.  
  230. @subsection Extending GDL
  231.  
  232. GDL has been designed so as to be relatively easily extensible.
  233. I say ``relatively'' because although it is quite easy to define a new
  234. keyword or table, it is not always so easy to integrate the implementation
  235. code into the kernel correctly.
  236.  
  237. Instead of actually changing GDL, you can experiment with an addition
  238. by using the @code{extensions} property of unit, material, and terrain types.
  239. In the code, you call @code{get_u_extension}, pass it the type, name
  240. of the property, and a default to return if the value was not given.
  241. In the game definition, the designer would say
  242. @code{(unit town (extensions (my-ext xxx)))}.
  243.  
  244. [show examples for global, property, table, event, task]
  245.  
  246. The file @code{gvar.def} defines all the global variables.
  247.  
  248. The file @code{utype.def} defines all the unit type properties.
  249.  
  250. From time to time, it may be worthwhile to extend unit objects.
  251. This should be rare, because games may have thousands of units,
  252. and each unit requires at least 100 bytes of storage already,
  253. so you should avoid making them any larger.
  254. Properties of an individual unit are scattered through @code{keyword.def}.
  255. Once the structure slot is added, you just need to add reading and
  256. writing of the value, using the @code{K_@var{xxx}} enum that was
  257. defined with the keyword.  You should attempt to make a reasonable
  258. default and use it to avoid writing out the value, so as to save
  259. time when @i{Xconq} reads a game in.
  260.  
  261. GDL symbols beginning with @code{zz-} should be reserved for the use
  262. of AI code.  You may want to add some of these, either to serve as a
  263. convenient place for AIs to cache the results of their analyis of a
  264. game, or else as a way for game designers to add ``hints'' for AIs
  265. that know to look at them.
  266.  
  267. Note that all the @samp{*.def} files together are to define the exact set
  268. of symbols defined by GDL.  You should not add any expedient matching
  269. on symbols or searching for particular symbols without adding them to
  270. an appropriate @samp{.def} file.
  271.  
  272. @node Interface, Networking, Kernel, Hacking Xconq
  273.  
  274. @section Interface
  275.  
  276. The player interface is how actual players interact with the game.
  277. It need not be graphical or even particularly interactive,
  278. in fact it could even be a network server-style interface!
  279. However, this section will concentrate on the construction
  280. of interactive graphical interfaces.
  281.  
  282. @menu
  283. * Interface Architecture::
  284. * Main Program::                
  285. * Startup Options::             
  286. * Progress Indication::         
  287. * Feedback and Control::        
  288. * Play Commands::                    
  289. * Error Handling::              
  290. * Textual Displays::            
  291. * Display Update::              
  292. * Types of Windows and Panels::  
  293. * Imaging::                     
  294. * Animation::                   
  295. * Game Designer Tools::         
  296. * Porting and Multiple Interfaces::  
  297. * Useful Displays::             
  298. * Useful Options::              
  299. * Debugging Aids::              
  300. * Guidelines and Suggestions::  
  301. @end menu
  302.  
  303. @node Interface Architecture, Main Program, Interface, Interface
  304.  
  305. @subsection Interface Architecture
  306.  
  307. An interface is always compiled in, so it has complete access to the
  308. game state.  However, if your version of @i{Xconq} has any networking
  309. support, the interface should not modify kernel structures directly,
  310. but should instead use kernel routines.  The kernel routines will
  311. forward any state modifications to all other programs participating
  312. in a game, so that everybody's state remains consistent.
  313.  
  314. A working interface must provide some level of capability in each
  315. of these areas:
  316.  
  317. @itemize
  318. @item
  319. Main program.
  320. The interface includes the main application and any
  321. system-specific infrastructure, such as event handling.
  322.  
  323. @item
  324. Interpretation of startup options.
  325. This includes choice of games, variants, and players.
  326.  
  327. @item
  328. Display of game state.
  329. This includes both textual and graphical displays,
  330. both static and dynamic.
  331.  
  332. @item
  333. Commands/gestures for unit tasks and actions,
  334. and for general state modifications.
  335.  
  336. @item
  337. Display update in response to state changes.
  338.  
  339. @item
  340. Realtime progress.
  341. Some game designs require the interface
  342. to support realtime.
  343.  
  344. @item
  345. Error handling.
  346. @end itemize
  347.  
  348. The file @code{skelconq.c} in the @code{kernel} directory is
  349. a good example of a minimum working interface.
  350.  
  351. Don't let interfaces ever set kernel object values directly, always
  352. go through calls that can be ``siphoned'' for networking.
  353.  
  354. @node Main Program, Startup Options, Interface Architecture, Interface
  355.  
  356. @subsection Main Program
  357.  
  358. The interface provides @code{main()} for @i{Xconq};
  359. this allows maximum flexibility in adapting to different environments.
  360. In a sense, the kernel is a large library that the
  361. interface calls to do game-related operations.
  362.  
  363. There is a standard set of calls that need to be made during
  364. initialization.  The set changes from time to time, so the
  365. following extract from @file{skelconq} should not be taken as
  366. definitive:
  367. @example
  368.     init_library_path(NULL);
  369.     clear_game_modules();
  370.     init_data_structures();
  371.     parse_command_line(argc, argv, general_options);
  372.     load_all_modules();
  373.     check_game_validity();
  374.     parse_command_line(argc, argv, variant_options);
  375.     set_variants_from_options();
  376.     parse_command_line(argc, argv, player_options);
  377.     set_players_from_options();
  378.     parse_command_line(argc, argv, leftover_options);
  379.     make_trial_assignments();
  380.     calculate_globals();
  381.     run_synth_methods();
  382.     final_init();
  383.     assign_players_to_sides();
  384.     init_displays();
  385.     init_signal_handlers();
  386.     run_game(0);
  387. @end example
  388. Note that this sequence is only straight-through for a simple command
  389. line option program; if you have one or more game setup dialogs, then
  390. you choose which to call based on how the players have progressed
  391. through the dialogs.  The decision points more-or-less correspond to
  392. the different @code{parse_command_line} calls in the example.
  393. You may also need to interleave some interface-specific calls;
  394. for instance, if you want to display side emblems in a player/side
  395. selection dialog, then you will need to arrange for the emblem images
  396. to be loaded and displayable, rather than doing it as part of opening
  397. displays.
  398.  
  399. Once a game is underway, the interface is basically self-contained,
  400. needing only to call @code{run_game} periodically to keep the
  401. game moving along.  @code{run_game} takes one argument which can
  402. be -1, 0, or 1.  If 1, then one unit gets to do one action, then
  403. the routine returns.  If 0, the calculations are gone through, but
  404. no units can act.  If -1, then all possible units will move before
  405. @code{run_game} returns.  This last case is not recommended for interactive
  406. programs, since moving all units in a large game may take a very long
  407. time; several minutes sometimes, and @code{run_game} may not necessarily
  408. call back to the interface very often.
  409.  
  410. @node Startup Options, Progress Indication, Main Program, Interface
  411.  
  412. @subsection Startup Options
  413.  
  414. Although there are many different ways to get a game started,
  415. you have three main categories of functionality to support:
  416. 1) selection of the game to play, 2) setting of variants, and
  417. 3) selection of players.  For command-line-using programs,
  418. the file @code{cmdline.c} need only be linked in to provide
  419. all of this functionality.  For graphical interfaces, you will
  420. need to design appropriate dialogs.  This can be a lot of work,
  421. exacerbated by the fact that these dialogs will be the first
  422. things that new @i{Xconq} players see, and will therefore shape
  423. their opinions about the quality of the interface and of the game.
  424.  
  425. [more detail about what has to be in dialogs?]
  426.  
  427. Interface code should check all player specs, not proceed with initialization
  428. until these are all valid.
  429.  
  430. Both standard and nonstandard variants should vanish from or be grayed out
  431. in dialog boxes if irrelevant to a selected game.
  432.  
  433. @node Progress Indication, Feedback and Control, Startup Options, Interface
  434.  
  435. @subsection Progress Indication
  436.  
  437. Some synthesis methods are very slow, and become even
  438. slower when creating large games, so the kernel will announce a slow process,
  439. provide regular updates, and signal when the process is done.  The interface
  440. should display this in some useful way.  In general, progress should always
  441. be displayed, although one could postpone displaying anything until after
  442. the first progress update, calculate an estimated time to completion, and
  443. not display anything if that estimate is for less than a few seconds.
  444. However, this is probably unnecessary.
  445.  
  446. @itemize
  447. @item
  448. @code{void announce_read_progress()}
  449.  
  450. The kernel calls this regularly while reading game definitions.
  451. Interfaces running on slow machines should use this to indicate that
  452. everything is still working; for instance, the Mac interface animates
  453. a special cursor that indicates reading is taking place.
  454.  
  455. @item
  456. @code{void announce_lengthy_process(char *msg)}
  457.  
  458. The kernel calls this at the beginning of each synthesis.  The argument
  459. is a readable string that the interface can show to players.
  460.  
  461. @item
  462. @code{void announce_progress(int pctdone)}
  463.  
  464. The kernel may call this at milestones within a synthesis.
  465. The number ranges from 0 to 100.
  466.  
  467. @item
  468. @code{void finish_lengthy_process()}
  469.  
  470. The kernel calls this at the end of a synthesis.
  471.  
  472. @end itemize
  473.  
  474. @node Feedback and Control, Play Commands, Progress Indication, Interface
  475.  
  476. @subsection Feedback and Control
  477.  
  478. The interface should provide visible feedback for every successful unit
  479. action initiated directly by the player, but it need not do so for failures,
  480. unless they are serious.  It is better to prevent nonsensical input,
  481. for instance by disabling menus and control panel items.  Simple interfaces
  482. such as for character terminals will have to relax these rules somewhat.
  483.  
  484. Interfaces should enable/disable display of lighting conditions.
  485.  
  486. @node Play Commands, Error Handling, Feedback and Control, Interface
  487.  
  488. @subsection Play Commands
  489.  
  490. There is no single correct way to support direct player control over units.
  491. Although keyboard commands and mouse clicks are obvious choices,
  492. it would be very cool to allow a pen or mouse to sketch a movement plan,
  493. or to be able to give verbal orders...
  494.  
  495. There is a common set of ASCII keyboard commands that are recommended
  496. for all @i{Xconq} interfaces that use a keyboard.
  497. These are defined in @code{kernel/cmd.def}.
  498. If you use these, @i{Xconq} players will be able to switch platforms
  499. and still use familiar commands.  @code{cmd.def} defines a single character,
  500. a command name, a help string, and a function name,
  501. always in the form @code{do_*}.
  502. However, @code{cmd.def} does not specify arguments, return types,
  503. or behavior of those functions, so each interface must still define
  504. its own command lookup and calling conventions.
  505.  
  506. Prefixed number args should almost always be repetitions.
  507.  
  508. If already fully fueled, refuel commands should come back immediately.
  509.  
  510. A quit cmd can always take a player out of the game, but player may have
  511. to agree to resign.  Player can also declare willingness to quit or draw
  512. without actually doing so, then resolution requires that everybody agree.
  513. If quitting but others continuing on, also have option of being a
  514. spectator.  Could have notion of "leaving game without declaring entire
  515. game a draw" for some players.
  516. Allow for a timeout and default vote in case some voters have disappeared
  517. mysteriously.
  518. Must never force a player to stay in.
  519. Add a notion of login/logout so a side can be inactive but untouchable,
  520. possibly freezes entire game if a side is inactive.
  521. 1. if one player or no scoring
  522.     confirm, then shut player down
  523.     if one player, then shut game down
  524. 2. if side is considered a sure win (how to tell? is effectively a win
  525. condition then) or all sides willing to draw
  526.     confirm, take side out, declare a draw, shut player down
  527. 3. if all sides willing to quit
  528.     take entire game down
  529. 4. ask about resigning - if yes,
  530.     resign, close display, keep game running
  531.    if no, ask if willing to quit and/or draw, send msg to other sides
  532. Kernel support limited to must_resign_to_quit(side), similar tests.
  533.  
  534. @node Error Handling, Textual Displays, Play Commands, Interface
  535.  
  536. @subsection Error Handling
  537.  
  538. The interface must provide implementations of these error-handling
  539. functions:
  540.  
  541. @itemize
  542. @item
  543. @code{void low_init_warning(str)}
  544.  
  545. This is for undesirable but not necessarily
  546. wrong things that happen while setting up a game.  For instance,
  547. if players start out too close or too far from each other, it will
  548. often affect the play of the game adversely, so the kernel issues
  549. a warning, therby giving the prospective players a chance to cancel
  550. the game and start over.  The kernel's warning message should
  551. indicate any likely results of continuing on, so the players can
  552. decide whether or not to chance it.
  553.  
  554. @item
  555. @code{low_init_error(str)}
  556.  
  557. This function should indicate a serious and unrecoverable error
  558. during initialization.  It should not return to its caller.
  559.  
  560. @item
  561. @code{low_run_warning(str)}
  562.  
  563. Warnings during the game are rare but not unknown.
  564. They are very often due to bugs in @code{Xconq}, so any
  565. occurrence should be investigated further.  It is possible
  566. for some game designs to have latent flaws that may result
  567. in a warning.
  568. In any case, the interface should allow the players to continue
  569. on, to save their game and quit, by calling @code{save_the_game},
  570. or else quit without saving anything.
  571.  
  572. @item
  573. @code{low_run_error(str)}
  574.  
  575. In the worst case, @i{Xconq} can get into a situation, such as
  576. memory exhaustion, where there is no way to continue.  The kernel
  577. will then call @code{run_error}, which should inform players that
  578. @i{Xconq} must shut itself down.  They do get the option of saving
  579. the game, and the routine should call @code{save_game_state??} to
  580. do this safely.  This routine should also not return to its caller.
  581.  
  582. @item
  583. @code{printlisp(obj)}
  584.  
  585. This is needed to print GDL objects to ``stdout'' or its equivalent.
  586.  
  587. @end itemize
  588.  
  589. @node Textual Displays, Display Update, Error Handling, Interface
  590.  
  591. @subsection Textual Displays
  592.  
  593. Text can take a long time to read, and can be difficult to provide
  594. in multiple human languages. (What, you thought only English speakers
  595. played @i{Xconq}?  Think again!)
  596. Therefore, text displays in the interfaces should be as minimal as
  597. possible, and derive from strings supplied in the game design,
  598. since they can be altered without rebuilding the entire program.
  599.  
  600. (@i{Xconq} is not, at the moment, completely localizable,
  601. but that is a design goal.)
  602.  
  603. @node Display Update, Types of Windows and Panels, Textual Displays, Interface
  604.  
  605. @subsection Display Update
  606.  
  607. Usually the interface's display is controlled by the player,
  608. but when @code{run_game} is executing, it will frequently change
  609. the state of an object in a way that needs to be reflected in the
  610. display immediately.  Examples include units leaving or entering
  611. a cell, sides losing or winning, and so forth.  The interface
  612. must define a set of callbacks that will be invoked by the kernel.
  613.  
  614. @itemize
  615. @item
  616. @code{update_cell_display(side, x, y, rightnow)}
  617.  
  618. [introduce area (radius or rect) update routines?]
  619.  
  620. @item
  621. @code{update_side_display(side, side2, rightnow)}
  622.  
  623. @item
  624. @code{update_unit_display(side, unit, rightnow)}
  625.  
  626. @item
  627. @code{update_unit_acp_display(side, unit, rightnow)}
  628.  
  629. @item
  630. @code{update_turn_display(side, rightnow)}
  631.  
  632. @item
  633. @code{update_action_display(side, rightnow)}
  634.  
  635. @item
  636. @code{update_action_result_display(side, unit, rslt, rightnow)}
  637.  
  638. @item
  639. @code{update_fire_at_display(side, unit, unit2, m, rightnow)}
  640.  
  641. @item
  642. @code{update_fire_at_display(side, unit, x, y, z, m, rightnow)}
  643.  
  644. @item
  645. @code{update_event_display(side, hevt, rightnow)}
  646.  
  647. @item
  648. @code{update_all_progress_displays(str, s)}
  649.  
  650. @item
  651. @code{update_clock_display(side, rightnow)}
  652.  
  653. @item
  654. @code{update_message_display(side, sender, str, rightnow)}
  655.  
  656. @item
  657. @code{update_everything()}
  658.  
  659. @end itemize
  660.  
  661. Each of these routines has a flag indicating whether the change may be
  662. buffered or not.
  663. To ensure that buffered data is actually onscreen,
  664. the kernel may call @code{flush_display_buffers()},
  665. which the interface must define.
  666.  
  667. @itemize
  668. @item
  669. @code{flush_display_buffers()}
  670.  
  671. @end itemize
  672.  
  673. These may or may not be called on reasonable sides, so the
  674. interface should always check first that @code{side} actually
  675. exists and has an active display.
  676. [If side has a "remote" display, then interface has to forward??
  677. No, because remote copy of game is synchronized and does own
  678. update_xxx calls more-or-less simultaneously]
  679.  
  680. Note that this is as much as the kernel interests itself in displays.
  681. Map, list, etc drawing and redrawing are under the direct control
  682. of the interface code.
  683.  
  684. Unix-hosted versions must provide @code{void close_displays()}
  685. for signal handlers to call.
  686.  
  687. @node Types of Windows and Panels, Imaging, Display Update, Interface
  688.  
  689. @subsection Types of Windows and Panels
  690.  
  691. @i{Xconq} is best with a window-style interface, either tiled
  692. or overlapping.  Overlapping is more flexible, but also more
  693. complicated for players.
  694. In the following discussion, "window" will refer to a logically
  695. unified part of the display,
  696. which can be either a distinct window or merely a panel
  697. embedded in some larger window.
  698.  
  699. The centerpiece window should be a map display.
  700. This will be the most-used window,
  701. since it will typically display more useful information
  702. than any other window.
  703. This means that it must also exhibit very good performance.
  704.  
  705. When a game starts up, the map display should be centered
  706. on one of the player's units, preferably one close to the
  707. center of all the player's units.
  708.  
  709. Another recommended window is a list of all the sides and where
  710. they stand in both the current turn and in the game as a whole.
  711. Each side's entry should include its name, a progress bar or
  712. other doneness indicator, and room for all the scores and scorekeepers
  713. that apply to that side.
  714.  
  715. If possible, you should also implement
  716. some kind of "face" or group of faces/expressions for a side,
  717. so get a barbarian's face to repn a side instead of generic.
  718. Could have interface generate remarks/balloons if face clicked on,
  719. perhaps a reason for feelings, slogan, citation of agreement or broken
  720. agreement, etc.
  721. Need 5 faces for hostile, unfavorable, neutral, favorable, friendly/trusting.
  722.  
  723. Overall status of side rules:
  724.  
  725. all grayed: out of game
  726.  
  727. grayed and x-ed out: lost
  728.  
  729. ???: won
  730.  
  731. Progress bar rules:
  732.  
  733. missing: no units or no ai/no display
  734.  
  735. grayed frame: no acting units
  736.  
  737. empty solid frame: all acted
  738.  
  739. part full, black: partly acted
  740.  
  741. part full, gray: finished turn
  742.  
  743. @node Imaging, Animation, Types of Windows and Panels, Interface
  744.  
  745. @subsection Imaging
  746.  
  747. Imaging is the process of drawing pictorial representations.
  748. Not every interface needs it. For instance the curses interface
  749. is limited to drawing two ASCII characters for each cell,
  750. and its imaging code just has to choose which two to draw.
  751. However, full-color bitmapped displays need more attention
  752. to the process of getting an image onscreen.
  753.  
  754. No graphical icon should be drawn smaller than about 8x8, unless it's
  755. a text character drawn in two contrasting colors.
  756.  
  757. Interfaces should cache optimal displays for each mag, not search
  758. for best image each time.
  759.  
  760. Could allow 1-n "display variants" for all images, and for each orientation of
  761. border and connection.
  762.  
  763. Imaging variations can be randomly selected by UI,
  764. but must be maintained so redraws are consistent.
  765.  
  766. Allow the 64 bord/conn combos as single images, also advantage
  767. that all will be drawn at once.
  768.  
  769. Draw partial cells around edges of a window, to indicate that the world
  770. continues on in that direction.
  771.  
  772. Interface needs to draw only the terrain (but including connections and
  773. borders) in edge cells.
  774.  
  775. Could draw grid by blitting large light pattern over world, do by inverting
  776. so is easy to turn on/off.  Do grids by changing hex size only in
  777. unpatterned color?
  778.  
  779. Draw large hexagon or rect in unseen-color after clearing window to bg
  780. stipple (if unseen-color different).  Polygon should be inside area
  781. covered by edge hexes, so unseen area more obvious.
  782. Make large unseen-pattern that includes question marks?
  783.  
  784. If picture not defined for a game, use some sort of nondescript image
  785. instead of leaving blank. (small "no picture available" for instance,
  786. like in yearbooks)
  787.  
  788. To display night, could invert everything (b/w) or do 25/50% black (color)
  789. (let game set, so some games could be all-black at night, nothing visible)
  790. (have day/night coverage for each utype?)
  791. World is totally lit if dimensions < half of world circumference and all
  792. six corners of hexagon have same lighting.  If world totally dark, can draw
  793. darkening mask once for entire map.
  794.  
  795. To display elevation, use deep blue -> light gray -> dark brown progression,
  796. maybe also contour lines?
  797. To draw contour lines, for each hex, look at each adj hex.  If on other
  798. side of contour's elev, compute interpolated point (in pixels) and save
  799. or draw a line to (one or both of the two) adj hex borders if they also
  800. have the contour line pass through.  Guaranteed that line is part of
  801. overall contour line.  Cheaper approach doesn't interpolate, just draws
  802. to midpoint of hex border (probably OK for small mags).
  803. Could maybe save contour lines once calculated (at each mag, lots of mem).
  804.  
  805. If multiple connection or border types, the interface should draw them offset
  806. slightly from each other.
  807.  
  808. @node Animation, Game Designer Tools, Imaging, Interface
  809.  
  810. @subsection Animation
  811.  
  812. In addition to basic imaging, you can also support requests
  813. for the playing of animations or @i{movies}.
  814.  
  815. The kernel just calls @code{schedule_movie} to create one,
  816. and then @code{play_movies} when it is time to run all the
  817. movies that have been scheduled.  It is up to the interface
  818. to do something useful.  Note that the kernel is not aware
  819. of the movies' timing, so it is better not to call @code{run_game}
  820. until all the movies have finished playing.  (Yes, this would
  821. be a good future enhancement!)
  822.  
  823. @itemize
  824.  
  825. @item
  826. @code{schedule_movie(side, movie_type, args...)}
  827.  
  828. @item
  829. @code{play_movies(sidemask)}
  830.  
  831. Run all of the animations, sounds, etc that were scheduled
  832. previously, for the sides enabled in the side mask.
  833. It is allowable for the interface not to act on any user input
  834. while these are playing.
  835.  
  836. @end itemize
  837.  
  838. Several types of movies are predefined, so your interface can
  839. recognize them specially.  These include @code{movie_miss},
  840. @code{movie_hit}, @code{movie_death}, which are scheduled
  841. for the appropriate outcomes of combat.
  842.  
  843. @node Game Designer Tools, Porting and Multiple Interfaces, Animation, Interface
  844.  
  845. @subsection Game Designer Tools
  846.  
  847. An interface is not required to provide any sort of online
  848. designing tools, or even to provide a way to enable the
  849. special design privileges.  Nevertheless, minimal tools
  850. can be very helpful, and you will often find that they are
  851. helpful in debugging the rest of the interface, since you
  852. can use them to construct test cases at any time.
  853.  
  854. A basic set of design tools should include a way to enable
  855. and disable designing for at least one side, a command to
  856. create units of a given type, and some sort of tool to set
  857. the terrain type at a given location.  A full set would
  858. include ``painting'' tools for all area layers, including
  859. geographical features, materials, weather, side views,
  860. and so forth - about a dozen in all.
  861.  
  862. A least one level of undo for designer actions is very
  863. desirable, although it may be hard to implement.
  864. A useful rule for layers is to save a layer's previous
  865. state at the beginning of each painting or other modification
  866. action, when the mouse button first goes down.
  867.  
  868. The designer will often want to save only the part of the game
  869. being worked on, for instance only the units or only the terrain.
  870. The "save game" action should give designers a choice about
  871. what to save.  For units particularly, the designer should be
  872. able to save only some properties of units.  The most basic
  873. properties are type, location, side, and name/number.
  874. The unit id should not be saved by default, but should have
  875. its own option (not clear why).
  876.  
  877. Note that because game modules are textual and can be
  878. moved easily from one system to another, it is entirely
  879. possible to use one @i{Xconq} (perhaps on a Mac) to design
  880. games to be played on a Unix box under X11, or vice versa.
  881. Transferring the imagery is more difficult, although there
  882. is some support for the process.
  883.  
  884. @node Porting and Multiple Interfaces, Useful Displays , Game Designer Tools, Interface
  885.  
  886. @subsection Porting and Multiple Interfaces
  887.  
  888. In theory, it is possible to compile multiple interfaces
  889. into a single @i{Xconq} program, but this would be hard at best.
  890. They would have to be multiplexed appropriately and not
  891. conflict anywhere in the address space.
  892. Sometimes this is intrinsically impossible;
  893. how could you compile the Mac and X interfaces into the same
  894. program, and would the result be a Mac application, a Unix program,
  895. or what?
  896.  
  897. @node Useful Displays, Useful Options, Porting and Multiple Interfaces, Interface
  898.  
  899. @subsection Useful Displays
  900.  
  901. This is a collection of minor but useful displays that might be worth
  902. adding to an interface.
  903.  
  904. A ``mouse over'' is a line or two of text that describes what the
  905. mouse/pointer is currently pointing at, and which updates automatically
  906. as the player moves the pointer around.  This is better for high-bandwidth
  907. interfaces, since there may be a lot of updating involved.  The volume
  908. can be reduced slightly by only redisplaying when the mouse moves, or,
  909. better, when what is being looked at changes.  This is probably best done
  910. by recalculating the line of text and then comparing it to what has been
  911. drawn already, although if the display is very fast, you may not save much
  912. in drawing time.  One approx 40-char lines covers basic info, such as
  913. terrain type and unit type; more detail may require multiple long lines.
  914.  
  915. @node Useful Options, Debugging Aids, Useful Displays, Interface
  916.  
  917. @subsection Useful Options
  918.  
  919. A ``follow action'' option scrolls the screen to where the last event
  920. happened, such as combat. [etc]
  921.  
  922. @node Debugging Aids, Guidelines and Suggestions, Useful Options, Interface
  923.  
  924. @subsection Debugging Aids
  925.  
  926. @i{Xconq} is complicated enough that you can't expect to throw together
  927. a complete working interface over the weekend.
  928. Therefore, you should build some debugging aids into the interface.
  929. You can ifdef with the flag @code{DEBUGGING} so as to ensure the code
  930. won't be in final versions.
  931.  
  932. Display unit id if closeups, toplines, etc, if debugging is on.
  933.  
  934. @node Guidelines and Suggestions,  , Debugging Aids, Interface
  935.  
  936. @subsection Guidelines and Suggestions
  937.  
  938. Although as the interface builder, you are free to make it work in any
  939. way you like, there are a number of basic things you should do.
  940. Some of these are general user interface principles, others are specific
  941. to @i{Xconq}, usually based on experiences with the existing interfaces.
  942. Applying some of these guidelines will require judicious balancing between
  943. consistency with the different version of @i{Xconq} and consistency with
  944. the system you're porting to.
  945.  
  946. [following items should be better organized, moved in with relevant sections]
  947.  
  948. Draw single selected unit in a stack larger.
  949.  
  950. Draw single selected occupant in UR corner next to transport, when at
  951. mags that show both transport and occs.
  952.  
  953. There should always be some sort of "what's happening now" display
  954. so player doesn't wonder about apparently dead machine.
  955.  
  956. Image tool should report which type of resource is generating a
  957. given image, so can find which to hack on (report for selected image only).
  958.  
  959. Interfaces should ensure stability of display choices
  960. if random possibilities, so need to cache local decisions about
  961. appearance of units if multiple images to choose from, choice of
  962. text messages, etc.
  963.  
  964. Rules of Interaction:
  965. 1. Player can get to any unit in any mode.
  966. 2. Any player can prevent a turn from completing(/progressing?),
  967.    unless a hard real limit is encountered.
  968. 3. All players see each others' general move/activity state, modes, etc.
  969. 4. Players can "nudge" each other.
  970. 5. Real time limits can be set for sides, turns, and games, both by players
  971.    and by scenarios.
  972.  
  973. Player should be able to click on a desired unit or image, and effectively
  974. say "take this", either grabs directly or else composes a task to approach
  975. and capture.
  976.  
  977. Unit closeups should be laid out individually for each type, too much
  978. variability to make a single format reasonable.
  979.  
  980. Add option where game design can specify use or avoidance of masks
  981. with unit icons.
  982.  
  983. Player could escape a loss by saving a game, then discarding save.
  984. Mplayers could register suspicion when player saves then quits -
  985. "You're not trying to cheat, are you?" - but can't prevent this.
  986.  
  987. All interfaces should be able to bring up an "Instructions" window
  988. that informs player(s) about the current game, includes xrefs to all
  989. game design info.  Restrict help to generic and interface info only.
  990.  
  991. Graph display should graphing of various useful values, such as amounts
  992. of units and materials over time, attitudes of sides, combat, etc.
  993. Maximal is timeline for all sides and units, usually too elaborate but
  994. allow tracking movement for some "important" units.  Note that move
  995. actions may be recorded anyway.
  996.  
  997. Make specialized dialog for agreements, put name on top, then scrolling list of
  998. terms, then signers, then random bits (public/secret, etc).  Use for proposals
  999. also, so allow for "tentative" signers, desired signers who have not looked at
  1000. agreement.  Be able to display truth of each term, but need test to know when
  1001. a side can know the truth of a term?
  1002.  
  1003. Interfaces should have a ``wake up dummy'' button that can be used by players
  1004. who have finished their turn, to prod other players not yet done.
  1005.  
  1006. Commands that are irrelevant for a game ought to be grayed out in
  1007. help displays, and error messages should identify as completely invalid
  1008. (or just not do anything, a la grayed Mac menu shortcuts).
  1009.  
  1010. Should be able to drag out a route and have unit follow it (user input
  1011. of a complete task sequence).
  1012.  
  1013. Hack formatting so that variable-width fonts usually work reasonably.
  1014.  
  1015. Add xref buttons to various windows to go to other relevant windows and
  1016. focus in.
  1017.  
  1018. The current turn or date should be displayed prominently and be visible
  1019. somewhere by default.
  1020.  
  1021. Add some high-level verbs as commands ("assault Berlin", "bomb London until
  1022. destroyed").
  1023.  
  1024. Don't draw outline boxes at mags that would let them get outside the hex.
  1025.  
  1026. If dating view data, allow it to gray out rather than disappear entirely.
  1027. Could even have a "fade time" for unit images...
  1028.  
  1029. Even if display is textual, use red text (and other colors) to indicate
  1030. dangerous conditions.
  1031.  
  1032. Next/prev unit controls should change map focus, even if screen
  1033. unaffected.
  1034.  
  1035. In general, ability to "select" a unit implies ability to examine,
  1036. but not control.  Control implies ability to select, however.
  1037.  
  1038. Use a builtin color matching a color name if possible, otherwise
  1039. use the imc definition.
  1040.  
  1041. Connections may need to be drawn differently in each of the two hexes
  1042. they involve, such as straits connecting to a sea.
  1043. (what is this supposed to mean?)
  1044.  
  1045. If cell cramped for space, show only one material type at a time,
  1046. require redraw to show amounts of a different type.
  1047.  
  1048. Draw time remaining both digitally and as hourglass, for all time
  1049. limits in effect.
  1050.  
  1051. Could tie map to follow a specified unit (or to flip there quickly
  1052. a la SimAnt).
  1053.  
  1054. Have a separate message window from notices, allow broadcasting w/o
  1055. specific msg command? (a "talk" window)
  1056.  
  1057. Redraw hexes exposed when a unit with a legend moves.
  1058. Truncate or move legend if would overlap some other unit/legend.
  1059.  
  1060. Put limits on the number of windows of each type, set up so will reuse
  1061. windows, except for ones that are "staked down".
  1062.  
  1063. Fix border removal so inter-hex boundary pixels are cleaned up also.
  1064.  
  1065. Need a specialized window or display to check on current scores
  1066. (showing actual situation vs what's still needed).
  1067. (Show both scorekeepers actually in force, as well as the others.)
  1068. Side display could also display scores relevant to that side.
  1069.  
  1070. Every unit plan display should have a place to record notes and general
  1071. info about the unit, add a slot to units also.  Use in scenarios.
  1072.  
  1073. Need a command for when a player can explicitly change the self-unit.
  1074.  
  1075. Players should be able to rename any named object.  The interface should
  1076. also provide a button or control to run any namer that might be available
  1077. to the unit.
  1078.  
  1079. Be able to select unit number display indep of unit name display,
  1080. and feature name display indep of unit names.
  1081.  
  1082. Don't draw things that xform to 0 pixel areas,
  1083. only draw the most important things if 1-4 pixels or so.
  1084.  
  1085. If time/effort to do action is > length of game, then interface
  1086. can disable that action permanently.
  1087.  
  1088. Use moving bar or gray under black to indicate reserve/asleep units.
  1089.  
  1090. @node Networking, Miscellany, Interface, Hacking Xconq
  1091.  
  1092. @section Networking
  1093.  
  1094. @i{Xconq} has been also been designed to allow for different kinds of
  1095. networking strategies.
  1096.  
  1097. The kernel/interface architecture can be exploited to build
  1098. a true server/client @i{Xconq},
  1099. by building an ``interface'' that manages IPC connections
  1100. and calling this the server, and then writing separate interface
  1101. programs that translate data at the other end of the IPC connection
  1102. into something that a display could use.
  1103. My previous attempt at this (ca 1989) was very slow and buggy,
  1104. though, so this is not necessarily an easy thing to write.
  1105. The chief problem is in keeping the client's view of thousands
  1106. of interlinked objects (units, sides, cells, and so forth)
  1107. consistent with the server.
  1108. Most existing server/client games work by either restricting
  1109. the state to a handful of objects,
  1110. or by only handing the client display-prepared data
  1111. rather than abstract data,
  1112. or by reducing the update interval
  1113. to minutes or hours.
  1114.  
  1115. [When networking, all kernels must call with same values...]
  1116.  
  1117. @node Miscellany, , Networking, Hacking Xconq
  1118.  
  1119. @section Miscellany
  1120.  
  1121. @menu
  1122. * Versioning Standards::        
  1123. * Coding Standards::
  1124. * Pitfalls::
  1125. * Rationale and Future Directions::
  1126. @end menu
  1127.  
  1128. @node Versioning Standards, Coding Standards, Miscellany, Miscellany
  1129.  
  1130. @subsection Versioning Standards
  1131.  
  1132. In version @var{7.x.y}, @var{x} should change only
  1133. when some documented user-visible aspect of @i{Xconq} changes,
  1134. whether in the interface or kernel.
  1135. In particular, any additions to GDL, such as a new table or
  1136. property, require a new @var{x} version.
  1137. @var{y} is reserved for bug-fix releases, which can include
  1138. the implementation of features that were documented but not
  1139. working correctly or completely.
  1140.  
  1141. The macro @code{VERSION} should also include a date in parentheses,
  1142. formatted in ``military style'', as in ``8 Jul 1995''.
  1143. Be sure to set the date to some approximation of the date of your
  1144. most recent change to the sources.
  1145.  
  1146. @node Coding Standards, Pitfalls, Versioning Standards, Miscellany
  1147.  
  1148. @subsection Coding Standards
  1149.  
  1150. The @i{Xconq} sources adhere to a number of coding standards that
  1151. you should follow also.  While everyone has their individual style,
  1152. it is important to the code's maintenance that the existing style
  1153. be preserved.
  1154.  
  1155. Always allocate by using @code{xmalloc}.  This routine checks for
  1156. allocation validity and gives a useful error message if allocation
  1157. fails, it zeroes the block so you can count on the newly allocated
  1158. space being in a known state, and it collects statistical data, which
  1159. is important to optimization.
  1160.  
  1161. Always generate a random number by using @code{xrandom}.  This is
  1162. a generator of known and consistent properties across all systems
  1163. that @i{Xconq} runs on.
  1164.  
  1165. Indent by 4, with tabs at 8.  This is effectively what you get in
  1166. Emacs if you set @code{c-indent-level} to 4.  System-specific interfaces
  1167. need not adhere to this rule..
  1168.  
  1169. @node Pitfalls, Rationale and Future Directions, Coding Standards, Miscellany
  1170.  
  1171. @subsection Pitfalls
  1172.  
  1173. This chapter would not be complete without some discussion of the traps
  1174. awaiting the unwary hacker.
  1175. The Absolute Number One Hazard in hacking @i{Xconq} is to introduce
  1176. code that does not work for @emph{all} game designs.
  1177. It is all too easy to assume that, for instance, unit speeds are always
  1178. less than 20, or airbases can only be built by infantry, or that worlds
  1179. are always randomly-generated.
  1180. These sorts of assumptions have caused no end of problems.
  1181. Code should test preconditions, especially for dynamically-allocated
  1182. game-specified objects, and it should be tested using the various
  1183. test scripts in the test directory.
  1184.  
  1185. The number two pitfall is to not account for all the possible interfaces.
  1186. Not all interfaces have a single ``current unit'' or map window,
  1187. and some communicate with multiple players or over a network connection.
  1188.  
  1189. You should not assume that your hack is generally valid until you have
  1190. tested it against everything in the library and test directories.
  1191. The @code{test} directory contains scripts that will be useful for this,
  1192. at least to Unix hackers.  See the @code{README} in that directory
  1193. for more information.
  1194.  
  1195. Another pitfall is to be sloppy about performance.  An algorithm that works
  1196. fine in a small world with two sides and 50 units may be painfully slow
  1197. in a large game. Or, the algorithm may allocate too much working space
  1198. and wind up exhausting memory (this has often happened).
  1199. You should familiarize yourself with the algorithms already used in @i{Xconq},
  1200. since they have already been debugged and tuned, and many have been written
  1201. as generically useful code (see the area-scanning functions in @code{world.c}
  1202. for instance).
  1203.  
  1204. If your new feature is expensive, then define a global and compute its value
  1205. only once, either at the start of the game or when it becomes relevant.
  1206. Such a global should be named @code{any_<feature>}.
  1207.  
  1208. Similarly, complicated tests on unit types or sides should be calculated
  1209. once and cached in a dynamically-allocated array.
  1210.  
  1211. You may have noticed that @i{Xconq} sources have been liberally sprinkled
  1212. with debugging code, and you may desire to add some yourself.  In this modern
  1213. age of computing, powerful source-level debuggers are widely available,
  1214. so there is no good reason to add debugging code that to do a job that
  1215. would be better done by the debugger.  @i{Xconq} debugging output
  1216. is generally designed to be useful for understanding average behavior,
  1217. changes over time, and ``high-level transients'' such as thrashing in
  1218. plan or task execution; information that is difficult to collect using only
  1219. a debugger.  When adding new debug output, you should keep this
  1220. principle in mind.  Also be aware that some of the automated testing scripts
  1221. enable debug output, so if you add something that is uselessly voluminous,
  1222. testing output may fill your disk prematurely!
  1223.  
  1224. @node Rationale and Future Directions, , Pitfalls, Miscellany
  1225.  
  1226. @subsection Rationale and Future Directions
  1227.  
  1228. This is where I justify what I've done, and not done.
  1229.  
  1230. Please note that although @i{Xconq} has considerable power,
  1231. its design was expressly limited to a particular class of two-dimensional
  1232. board-like strategy games, and that playability  is emphasized over
  1233. generality.  For instance, I avoided the temptation to include a
  1234. general-purpose language, since it opens up many difficult issues
  1235. and makes it much harder for game designers to produce a desired
  1236. game (after all, if game designers wanted to use a general-purpose
  1237. programming language, they could just write C code!).  Similarly,
  1238. full 3D, realtime maneuvering, continuous terrain, and other such goodies
  1239. must await the truly ultimate game system.
  1240.  
  1241. The real problem with a general-purpose language is that although
  1242. everything is possible, nothing is easy.  Many ``adventure game
  1243. writing systems'' have fallen into this trap; they end up being
  1244. poor reimplementations of standard programming languages, and the
  1245. sole support for adventure gaming amounts to a small program
  1246. skeleton and a few library functions.  It would have been easier
  1247. just to start with a pre-existing language and just write the
  1248. skeleton and libraries!
  1249.  
  1250. @i{Xconq}, on the other hand, provides extensive optimized support
  1251. for random game setup, large numbers of units, game save/restore,
  1252. computer opponents, and many other facets of a game.
  1253. Game designers don't have to deal with
  1254. the subleties of fractal terrain synthesis, or the ordering of
  1255. terrain effects on units, or how to tell the computer opponents
  1256. that airbases are sometimes good for refueling but never any
  1257. good for transportation, or the myriad of other details that
  1258. are wired into @i{Xconq}.
  1259. In fact, a complete working game can be set up with less than
  1260. a half-page of GDL.
  1261.  
  1262. Even so, the current @i{Xconq} design allows for several layers
  1263. of extensibility, as was described earlier in this chapter.
  1264.  
  1265. There are also several major areas in which @i{Xconq}
  1266. could be improved.
  1267.  
  1268. Tables should be supplemented with general formulae, although
  1269. such formulae will complicate AIs' analyses considerably,
  1270. since tables are much easier to scan.  Formula-based game
  1271. definition would work much better with AIs that are coded
  1272. specifically for the game and compiled in; this is more-or-less
  1273. possible now, but there is not yet a good way to keep AIs
  1274. from being used in games where they would be inappropriate
  1275. (it might be amusing to have a panzer general AI attempting
  1276. to play Gettysburg, but the coding would have to be careful
  1277. not to try to index nonexistent unit types).
  1278.  
  1279. Currently everything is based on a single area of a single world.
  1280. This could be extended to multiple areas in the world, perhaps
  1281. at different scales, as well as to multiple worlds.
  1282.  
  1283. However, even with its limitations, @i{Xconq} has provided,
  1284. and will continue to provide, many years of enjoyable playing,
  1285. designing, and hacking.  Go to it!
  1286.  
  1287.